-- Top Level Structural Model, TOP_SPIM
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;

USE WORK.COMPONENTS.ALL;
use work.types.all;

ENTITY TOP_SPIM IS
	PORT (
		reset, clock	: IN STD_LOGIC;
		instruct_out	: OUT INSTRUCTION;
		pc_out			: OUT MEMADDR;
		pc_plus_4_out	: OUT MEMADDR;
		read_data_1_out: OUT MEMDATA;
		read_data_2_out: OUT MEMDATA
	);
END 	TOP_SPIM;

ARCHITECTURE structure OF TOP_SPIM IS
	        
                -- Declaracao dos sinais usados para interligar os 5 componentes do mips
	        SIGNAL PC_plus_4_IF 	:  MEMADDR;
                SIGNAL PC_plus_4_ID 	:  MEMADDR;
                SIGNAL PC_plus_4_EX 	:  MEMADDR;
        
	        SIGNAL read_data_1_ID 	:  MEMDATA;
	        SIGNAL read_data_1_EX 	:  MEMDATA;

	        SIGNAL read_data_2_ID 	:  MEMDATA;
	        SIGNAL read_data_2_EX 	:  MEMDATA;
	        SIGNAL read_data_2_MEM 	:  MEMDATA;
        
	        SIGNAL Sign_Extend_ID 	:  MEMDATA;
	        SIGNAL Sign_Extend_EX 	:  MEMDATA;
        
	        SIGNAL Add_result_EX 	:  MEMADDR;
	        SIGNAL Add_result_MEM 	:  MEMADDR;
        
        
	        SIGNAL ALU_result_EX 	:  MEMDATA;
	        SIGNAL ALU_result_MEM 	:  MEMDATA;
	        SIGNAL ALU_result_WB 	:  MEMDATA;
        
	        SIGNAL read_data_MEM 	:  MEMDATA;
	        SIGNAL read_data_WB 	:  MEMDATA;
        
	        SIGNAL ALUSrc_ID	:  STD_LOGIC;
	        SIGNAL ALUSrc_EX	:  STD_LOGIC;
        
	        SIGNAL Branch_ID	:  STD_LOGIC;
	        SIGNAL Branch_EX	:  STD_LOGIC;
	        SIGNAL Branch_MEM	:  STD_LOGIC;
        
	        SIGNAL RegDst 		:  STD_LOGIC;
        
	        SIGNAL Regwrite_ID 	:  STD_LOGIC;
	        SIGNAL Regwrite_EX 	:  STD_LOGIC;
	        SIGNAL Regwrite_MEM 	:  STD_LOGIC;
	        SIGNAL Regwrite_WB 	:  STD_LOGIC;
        
	        SIGNAL Zero_EX 		:  STD_LOGIC;
	        SIGNAL Zero_MEM		:  STD_LOGIC;

	        SIGNAL MemWrite_ID	:  STD_LOGIC;
	        SIGNAL MemWrite_EX	:  STD_LOGIC;
	        SIGNAL MemWrite_MEM	:  STD_LOGIC;
        
	        SIGNAL MemtoReg_ID 	:  STD_LOGIC;
	        SIGNAL MemtoReg_EX 	:  STD_LOGIC;
	        SIGNAL MemtoReg_MEM 	:  STD_LOGIC;
	        SIGNAL MemtoReg_WB 	:  STD_LOGIC;
        
	        SIGNAL MemRead_ID	:  STD_LOGIC;
	        SIGNAL MemRead_EX	:  STD_LOGIC;
	        SIGNAL MemRead_MEM	:  STD_LOGIC;
        
	        SIGNAL ALUop_ID		:  STD_LOGIC_VECTOR(  1 DOWNTO 0 );
	        SIGNAL ALUop_EX		:  STD_LOGIC_VECTOR(  1 DOWNTO 0 );
        
	        SIGNAL Instruct_IF	:  INSTRUCTION;
	        SIGNAL Instruct_ID	:  INSTRUCTION;
        
                SIGNAL WrAddr_EX        :  REGADDR;
                SIGNAL WrAddr_MEM       :  REGADDR;
                SIGNAL WrAddr_WB        :  REGADDR;
                SIGNAL PC               :  MEMADDR;
BEGIN
	pc_out <= PC;
	pc_plus_4_out <= PC_plus_4_IF;
	instruct_out <= Instruct_IF;
	read_data_1_out <= read_data_1_ID;
	read_data_2_out <= read_data_2_ID;
	

  --Conexao dos 5 componentes do MIPS
  IFE : Ifetch
	PORT MAP (	Instruct 	=> Instruct_IF,
			PC_plus_4_out 	=> PC_plus_4_IF,
			Add_result 	=> Add_result_MEM,
			Branch 		=> Branch_MEM,
			Zero 		=> Zero_MEM,
			PC_out 		=> PC,        		
			clock 		=> clock,  
			reset 		=> reset );

  IFID: IF_ID
        PORT MAP(
                        clock           => clock,
                        reset           => reset,
                        NextPc_in       => PC_plus_4_IF,
                        NextPc_out      => PC_plus_4_ID,
                        Instruct_in  => Instruct_IF,
                        Instruct_out => Instruct_ID
                );

  ID : Idecode
  	PORT MAP (	read_data_1 	=> read_data_1_ID,
			read_data_2 	=> read_data_2_ID,
			Instruct 	=> Instruct_ID,
			read_data 	=> read_data_WB,
			ALU_result 	=> ALU_result_WB,
			RegWrite 	=> RegWrite_WB,
			MemtoReg 	=> MemtoReg_WB,
			--RegDst 		=> RegDst,
         WrAddr          => WrAddr_WB,
			Sign_extend 	=> Sign_extend_ID,
			clock 		=> clock,  
			reset 		=> reset );


  CTL:   control
	PORT MAP ( 	Opcode 		=> Instruct_ID( 31 DOWNTO 26 ),
			RegDst 		=> RegDst,
			ALUSrc 		=> ALUSrc_ID,
			MemtoReg	=> MemtoReg_ID,
			RegWrite        => RegWrite_ID,
			MemRead         => MemRead_ID,
			MemWrite	=> MemWrite_ID,
			Branch 		=> Branch_ID,
			ALUop 		=> ALUop_ID,
			clock 		=> clock,
			reset 		=> reset );
  
  IDEX: ID_EX
        PORT MAP(
                        clock           => clock,
                        reset           => reset,

                        NextPc_in       => PC_plus_4_ID,
                        NextPc_out      => PC_plus_4_EX,

                        RegDst_in       => RegDst,
                        ALUSrc_in       => ALUSrc_ID,
	                MemtoReg_in     => MemtoReg_ID,
	                RegWrite_in     => RegWrite_ID,
	                MemRead_in      => MemRead_ID,
	                MemWrite_in     => MemWrite_ID,
	                Branch_in       => Branch_ID,
	                ALUop_in        => ALUop_ID,
                        ALUSrc_out      => ALUSrc_EX,

	                MemtoReg_out    => MemtoReg_EX,
	                RegWrite_out    => RegWrite_EX,
	                MemRead_out     => MemRead_EX,
	                MemWrite_out    => MemWrite_EX,
	                Branch_out      => Branch_EX,
	                ALUop_out       => ALUop_EX,

                        read_data_1_in  => read_data_1_ID,
        		read_data_2_in  => read_data_2_ID,
                        Sign_extend_in	=> Sign_Extend_ID,
        
                        read_data_1_out => read_data_1_EX,
	                read_data_2_out => read_data_2_EX,
                        Sign_extend_out	=> Sign_Extend_EX,

                        WrAddr_0        => Instruct_ID( 20 DOWNTO 16 ),
                        WrAddr_1        => Instruct_ID( 15 DOWNTO 11 ),
                        WrAddr_out      => WrAddr_EX

                );

  EXE:  Execute
	PORT MAP (	Read_data_1 	=> read_data_1_EX,
			Read_data_2 	=> read_data_2_EX,
			Sign_extend 	=> Sign_extend_EX,
			--Function_opcode => Instruct( 5 DOWNTO 0 ),
                        Function_opcode => Sign_Extend_EX( 5 DOWNTO 0 ),
			ALUOp 		=> ALUop_EX,
			ALUSrc 		=> ALUSrc_EX,
			Zero 		=> Zero_EX,
			ALU_Result	=> ALU_Result_EX,
			Add_Result 	=> Add_Result_EX,
			PC_plus_4	=> PC_plus_4_EX,
			Clock		=> clock,
			Reset		=> reset );

  EXMEM: EX_MEM
        PORT MAP (
                        clock  => clock,
                        reset  => reset,

        	        Regwrite_in 	=> Regwrite_EX,
	                MemtoReg_in 	=> MemtoReg_EX,
	                MemRead_in	=> MemRead_EX,
                        MemWrite_in     => MemWrite_EX,
                        Branch_in       => Branch_EX,
	                read_data_2_in 	=> read_data_2_EX,

        	        Regwrite_out 	=> Regwrite_MEM,
	                MemtoReg_out 	=> MemtoReg_MEM,
	                MemRead_out	=> MemRead_MEM,
                        MemWrite_out    => MemWrite_MEM,
                        Branch_out      => Branch_MEM,
	                read_data_2_out => read_data_2_MEM,

                        Add_result_in 	=> Add_result_EX,
                        WrAddr_in       => WrAddr_EX,
	                Add_result_out 	=> Add_result_MEM,
                        WrAddr_out      => WrAddr_MEM,
        
	                Zero_in 	=> Zero_EX,
	                Zero_out	=> Zero_MEM,
	                ALU_result_in 	=> ALU_result_EX,
        	        ALU_result_out 	=> ALU_result_MEM
                        
                 );

  MEM:  dmemory
	PORT MAP (		read_data       => read_data_MEM,
				address 	=> ALU_Result_MEM,
				write_data	=> read_data_2_MEM,
				MemRead 	=> MemRead_MEM, 
				Memwrite        => MemWrite_MEM, 
				clock 	        => clock,  
				reset 	        => reset );
  MEMWB: MEM_WB
        PORT MAP (
                        clock  => clock,
                        reset  => reset,

                        RegWrite_in     => RegWrite_MEM,
                        MemtoReg_in     => MemtoReg_MEM,
                        ReadData_in     => read_data_MEM,
                        ALU_result_in   => ALU_result_MEM,
                        WrAddr_in       => WrAddr_MEM,

                        RegWrite_out     => RegWrite_WB,
                        MemtoReg_out     => MemtoReg_WB,
                        ReadData_out     => read_data_WB,
                        ALU_result_out   => ALU_result_WB,
                        WrAddr_out       => WrAddr_WB
                 );
END structure;


